{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Populating the interactive namespace from numpy and matplotlib\n"
     ]
    }
   ],
   "source": [
    "%pylab inline\n",
    "from fractions import Fraction as F\n",
    "from operator import add, mul, sub, truediv\n",
    "from sympy import Symbol as S, solve, latex, sympify"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "class LeafNode:\n",
    "    def __init__(self):\n",
    "        self._value = F(np.random.randint(1, 100), 1)\n",
    "        self._symbol = S(str(self.value.numerator))\n",
    "        self._replace = None\n",
    "        \n",
    "    @property\n",
    "    def value(self):\n",
    "        return self._value\n",
    "    \n",
    "    @property\n",
    "    def depth(self):\n",
    "        return 1\n",
    "    \n",
    "    @property\n",
    "    def expression(self):\n",
    "        return self._symbol if self._replace is None else self._replace\n",
    "        \n",
    "class NotLeafNode:\n",
    "    gens = {'add': add, 'mul': mul, 'sub': sub, 'truediv': truediv}\n",
    "    \n",
    "    def __init__(self):\n",
    "        self.type = np.random.choice(list(self.gens.keys()))\n",
    "        self.left = np.random.choice([LeafNode, NotLeafNode], p=[.6, .4])()\n",
    "        self.right = np.random.choice([LeafNode, NotLeafNode], p=[.6, .4])()\n",
    "    \n",
    "    @property\n",
    "    def value(self):\n",
    "        return self.gens[self.type](self.left.value, self.right.value)\n",
    "    \n",
    "    @property\n",
    "    def depth(self):\n",
    "        return max(self.left.depth, self.right.depth) + 1\n",
    "    \n",
    "    @property\n",
    "    def expression(self):\n",
    "        return self.gens[self.type](self.left.expression, self.right.expression)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "def assgin_x(root, num):\n",
    "    if isinstance(root, LeafNode):\n",
    "        if root.value.numerator == num:\n",
    "            root._replace = S('x')\n",
    "        else:\n",
    "            root._replace = None\n",
    "    else:\n",
    "        assgin_x(root.left, num)\n",
    "        assgin_x(root.right, num)\n",
    "        \n",
    "def clear_x(root):\n",
    "    if isinstance(root, LeafNode):\n",
    "        root._replace = None\n",
    "    else:\n",
    "        clear_x(root.left)\n",
    "        clear_x(root.right)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "def gen_root():\n",
    "    while True:\n",
    "        root = NotLeafNode()\n",
    "        if 3 <= root.depth <= 6:\n",
    "            break\n",
    "    print(root.value)\n",
    "    return root"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "def write_1(root, filename='作业'):\n",
    "    clear_x(root)\n",
    "    expr = root.expression\n",
    "    question = latex(expr)\n",
    "    answer = latex(S(str(root.value.numerator)) / S(str(root.value.denominator)) if root.value.denominator != 1 else S(str(root.value.numerator)))\n",
    "    q1 = f'$ \\displaystyle {question} = $\\n\\n'\n",
    "    q2 = f'$ \\displaystyle {question} = {answer} $\\n\\n'\n",
    "    with open(f'{filename}.txt', 'a') as f:\n",
    "        f.write(q1)\n",
    "    with open(f'{filename} - 答案.txt', 'a') as f:\n",
    "        f.write(q2)\n",
    "    return expr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "def write_2(root, unk, filename='作业'):\n",
    "    clear_x(root)\n",
    "    expr = solve(root.expression - root.value, S(str(unk)))[0]\n",
    "    question = latex(expr)\n",
    "    answer = latex(S(str(unk)))\n",
    "    q1 = f'$ \\displaystyle {question} = $\\n\\n'\n",
    "    q2 = f'$ \\displaystyle {question} = {answer} $\\n\\n'\n",
    "    with open(f'{filename}.txt', 'a') as f:\n",
    "        f.write(q1)\n",
    "    with open(f'{filename} - 答案.txt', 'a') as f:\n",
    "        f.write(q2)\n",
    "    return expr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "def write_3(root, unk, filename='作业'):\n",
    "    clear_x(root)\n",
    "    assgin_x(root, unk)\n",
    "    expr = root.expression\n",
    "    question = latex(expr)\n",
    "    right = latex(S(str(root.value.numerator)) / S(str(root.value.denominator)) if root.value.denominator != 1 else S(str(root.value.numerator)))\n",
    "    answer = latex(S(str(unk)))\n",
    "    q1 = f'$ \\displaystyle {question} = {right} $\\n\\n'\n",
    "    q2 = f'$ \\displaystyle {question} = {right} $ `Ans` $ x = {answer} $\\n\\n'\n",
    "    with open(f'{filename}.txt', 'a') as f:\n",
    "        f.write(q1)\n",
    "    with open(f'{filename} - 答案.txt', 'a') as f:\n",
    "        f.write(q2)\n",
    "    return expr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 138,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "24/7\n"
     ]
    },
    {
     "data": {
      "text/latex": [
       "$\\displaystyle \\frac{3 \\cdot 72}{63}$"
      ],
      "text/plain": [
       "3*72/63"
      ]
     },
     "execution_count": 138,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "root = gen_root()\n",
    "root.expression"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 139,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle \\frac{24 \\cdot 63}{7 \\cdot 72}$"
      ],
      "text/plain": [
       "24*63/(7*72)"
      ]
     },
     "execution_count": 139,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "unk = 3\n",
    "clear_x(root)\n",
    "solve(root.expression - root.value, S(str(unk)))[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 127,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle \\frac{83 \\left(17 - 77\\right)}{x}$"
      ],
      "text/plain": [
       "83*(17 - 77)/x"
      ]
     },
     "execution_count": 127,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "assgin_x(root, unk)\n",
    "root.expression"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 97,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle \\frac{50 \\cdot 54}{36}$"
      ],
      "text/plain": [
       "50*54/36"
      ]
     },
     "execution_count": 97,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "write_1(root)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 140,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle \\frac{24 \\cdot 63}{7 \\cdot 72}$"
      ],
      "text/plain": [
       "24*63/(7*72)"
      ]
     },
     "execution_count": 140,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "write_2(root, unk)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 128,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle \\frac{83 \\left(17 - 77\\right)}{x}$"
      ],
      "text/plain": [
       "83*(17 - 77)/x"
      ]
     },
     "execution_count": 128,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "write_3(root, unk)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
